package com.google.code.sfa.util;

import java.util.*;
import org.biojava.bio.symbol.Symbol;
import org.biojava.bio.seq.DNATools;
import org.biojava.bio.symbol.AlphabetManager;

public class DNASymbolSet implements Set<Symbol> {
    
    public byte a,t,c,g,gap;

    public DNASymbolSet() {
	clear();
    }

    public Symbol getBestSymbol() {
	if( a >= t && a >= c && a >= g && a >= gap) {
	    return DNATools.a();
	}
	if( t >= c && t >= g && t >= gap) {
	    return DNATools.t();
	}
	if( c >= g && c >= gap) {
	    return DNATools.c();
	}
	if( g >= gap) {
	    return DNATools.g();
	}
	return DNATools.getDNA().getGapSymbol();
    }

    public String toString() {
	return repeat("a",a) + repeat("t",t) + repeat("c",c) + repeat("g",g) + repeat("-",gap);
    }
    private String repeat(String s, byte times) {
	String out = "";
	for( byte i = 0; i < times; i++) {
	    out += s;
	}
	return out;
    }

    public boolean add( Symbol s) {
	if( s == DNATools.a()) {
	    a++;
	    return (a==1);
	} else if( s == DNATools.t()) {
	    t++;
	    return (t==1);
	} else if( s == DNATools.c()) {
	    c++;
	    return (c==1);
	} else if( s == DNATools.g()) {
	    g++;
	    return (g==1);
	} else if( s == DNATools.getDNA().getGapSymbol() ) {
	    gap++;
	    return (gap==1);
	}
	return false;
    }

    public boolean addAll(Collection<? extends Symbol> col) {
	boolean changed = false;
	for( Symbol s : col) {
	    changed = changed || add(s);
	}
	return changed;
    }

    public void clear() {
	a = 0;
	t = 0;
	c = 0;
	g = 0;
	gap = 0;
    }

    public boolean contains(Object o) {
	if( ! (o instanceof Symbol)) {
	    return false;
	}

	return 
	    ( a > 0 && o == DNATools.a()) ||
	    ( t > 0 && o == DNATools.t()) ||
	    ( c > 0 && o == DNATools.c()) ||
	    ( g > 0 && o == DNATools.g()) ||
	    ( gap > 0 && o == DNATools.getDNA().getGapSymbol());
    } 

    public boolean containsAll(Collection<?> col) {
	for( Object s : col) {
	    if( ! contains(s) ) {
		return false;
	    }
	}
	return true;
    }

    public boolean equals(Object o) {
	if( ! (o instanceof Set)) {
	    return false;
	}

	
	Set s = (Set) o;
	return 
	    ((a > 0) == s.contains( DNATools.a()) ) || 
	    ((t > 0) == s.contains( DNATools.t()) ) || 
	    ((c > 0) == s.contains( DNATools.c()) ) || 
	    ((g > 0) == s.contains( DNATools.g()) ) ||
	    ((gap > 0) == s.isEmpty());
    }
    
    public int hashCode() {
	return
	    (new Integer(a)).hashCode() ^
	    (new Integer(t)).hashCode() ^
	    (new Integer(c)).hashCode() ^
	    (new Integer(g)).hashCode() ^
	    (new Integer(gap)).hashCode();
    }

    public boolean isEmpty() {
	return a == 0 && t == 0 && c == 0 && g == 0;
    }

    public Iterator<Symbol> iterator() {
	return toList().iterator();
    }

    public boolean remove(Object o) {
	if( ! (o instanceof Symbol)) {
	    return false;
	}
	if( a > 0 && o == DNATools.a()) {
	    a--;
	} else if( t > 0 && o == DNATools.t()) {
	    t--;
	} else if( c > 0 && o == DNATools.c()) {
	    c--;
	} else if( g > 0 && o == DNATools.g()) {
	    g--;
	} else if( gap > 0 && o == DNATools.getDNA().getGapSymbol()) {
	    gap--;
	} else {
	    return false;
	}

	return true;
    }

    public boolean removeAll( Collection<?> c) {
	throw new java.lang.UnsupportedOperationException();
/*	boolean changed = false;
	for( Symbol s : c) {
	    changed = changed || remove(s);
	}
	return changed;*/
    }

    public boolean retainAll( Collection<?> c) {
	throw new java.lang.UnsupportedOperationException();
    }

    public int totalSize() {
	return a + t + c + g + gap;
    }

    public int size() {
	return
	    ((a > 0)?1:0) +
	    ((t > 0)?1:0) +
	    ((c > 0)?1:0) +
	    ((g > 0)?1:0);
    }

    public Object[] toArray() {
	return toList().toArray();
    }

    public <T> T[] toArray(T[] a) {
	return (T[]) toList().toArray();
    }

    private List<Symbol> toList() {
	List<Symbol> list = new ArrayList<Symbol>();
	if( a > 0) { list.add( DNATools.a()); }
	if( t > 0) { list.add( DNATools.t()); }
	if( c > 0) { list.add( DNATools.c()); }
	if( g > 0) { list.add( DNATools.g()); }
	if( gap > 0) { list.add( DNATools.getDNA().getGapSymbol()); }
	return list;
    }
}



    